﻿using System;
using System.Collections.Generic;
using System.Xml.Linq;
using System.Linq;
using Repetition.Domain;

namespace Repetition.Conversion
{
    public class XElementConverter
    {
        public static XElement ToXElement(Problem problem)
        {
            return new XElement("Problem",
                new XElement("Question", problem.Question),
                new XElement("Answer", problem.Answer),
                new XElement("Difficulty", problem.Difficulty),
                new XElement("Importance", problem.Importance),
                CreateSubjectReferenceList(problem.Subjects));
        }

        public static XElement ToXElement(Subject subject)
        {
            return new XElement("Subject",
                new XElement("Name", subject.Name),
                new XElement("Details", subject.Details));
        }

        public static XElement ToXElement(ICollection<Subject> subjects)
        {
            XElement subjectList = new XElement("Subjects");

            foreach (var subject in subjects)
                subjectList.Add(ToXElement(subject));

            return subjectList;
        }

        public static XElement ToXElement(ICollection<Problem> problems)
        {
            XElement problemList = new XElement("Problems");

            foreach (var problem in problems)
                problemList.Add(ToXElement(problem));

            return problemList;
        }

        public static XElement ToXElement(ICollection<Subject> subjects, ICollection<Problem> problems)
        {
            return new XElement("ProblemCollection",
                ToXElement(subjects),
                ToXElement(problems));
        }

        public static void Import(XElement element, out ICollection<Subject> subjects, out ICollection<Problem> problems)
        {
            subjects = new List<Subject>();
            problems = new List<Problem>();

            var subjectElements = from XElement s in element.Element("Subjects").Elements("Subject")  select s;
            var problemElements = from XElement p in element.Element("Problems").Elements("Problem") select p;

            foreach (var e in subjectElements)
                subjects.Add(GetSubjectFromXElement(e));

            foreach (var e in problemElements)
                problems.Add(GetProblemFromXElement(e, subjects));
        }

        public static Problem GetProblemFromXElement(XElement element, ICollection<Subject> availableSubjects)
        {
            Problem problem = new Problem(element.Element("Question").Value, element.Element("Answer").Value);

            var subjectNames = from XElement e in element.Element("Subjects").Elements("Subject")
                           select e.Value;

            foreach (var name in subjectNames)
                problem.AddSubject(GetSubjectByName(name, availableSubjects));

            return problem;
        }

        public static Subject GetSubjectFromXElement(XElement element)
        {
            return new Subject(element.Element("Name").Value, element.Element("Details").Value);
        }

        private static Subject GetSubjectByName(string name, ICollection<Subject> subjects)
        {
            foreach (var subject in subjects)
            {
                if (name == subject.Name)
                    return subject;
            }

            return null;
        }

        private static XElement CreateSubjectReferenceList(ICollection<Subject> subjects)
        {
            XElement subjectList = new XElement("Subjects");

            foreach (var subject in subjects)
                subjectList.Add(new XElement("Subject", subject.Name));

            return subjectList;
        }
    }
}